package com.imdroid.lite.net.udp;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import com.imdroid.lite.IMDroid;

public class UDPServer {
	/**
	 * 实际处理服务的线程组，管理着一个UDP请求守护线程。
	 */
	private static ExecutorService service;
	private static ExecutorService heartBeatService;
	/**
	 * 服务器工作存根，用于退出服务。
	 */
	private static Future<Void> future;
	/**
	 * HeartBeat工作存根，用于退出服务时的清理
	 */
	private static Future<Void> heartBeatFuture;
	
	private static DatagramSocket socket;
	

	public static void startup() throws Exception {
		if (service != null) {
			System.out.println("Already started ... at port " + socket.getPort());
			return;
		}
		
		System.out.println("Server starting ... ");
		
		// 启动容纳3个处理信息的线程的线程池
		NotificationGenerator.startupNotificationWorkers(3);
		service = Executors.newSingleThreadExecutor();
		future = service.submit(new Callable<Void>() {
			@Override
			public Void call() throws Exception {
				socket = new DatagramSocket();
				socket.send(getConnectPacket(true)); // 发送信息到服务器，触发连接
				while (true) {
					DatagramPacket packet = new DatagramPacket(new byte[548],
							548);
					socket.receive(packet);
					System.out.println("packet received ... ");
					NotificationGenerator.tryGenerateNotification(packet);
				}
			}

		});
		heartBeatService = Executors.newSingleThreadExecutor();
		heartBeatFuture = heartBeatService.submit(new Callable<Void>(){
			public Void call() throws Exception{
				while(true){
					System.out.println("begin heart beat ... ");
					try{
						Thread.sleep(45000); // 放宽一点，45秒进行一次HeartBeat
					} catch(Exception e){
						e.printStackTrace();
					}
					sendPacket(getConnectPacket(false));
				}
			}
		});
	}
	
	public static DatagramPacket getConnectPacket(boolean isFirstTime){
		// 这个包信息同时也用作心跳包。
		byte[] data = new byte[15];
		data[0] |= 1 << 4; // 表示只发送到服务器的信息
		System.arraycopy(IntegerTransfer.longToByte(
				System.currentTimeMillis()), 0, data, 2, 8); // 设置信息ID
		System.arraycopy(IntegerTransfer.intToByte(
				IMDroid.getUser().getUser_id()), 0, data, 10, 4); // 用户号(发送者)
		data[1] = FileTypes.CONNECT; // 设置请求类型
		data[14] = (byte)(isFirstTime ? 1 : 0);
		DatagramPacket packet = new DatagramPacket(data, 15);
		packet.setAddress(ServerAddress.address);
		packet.setPort(ServerAddress.port);
		return packet;
	}
	
	public static void shutdown(){
		if(heartBeatService != null && !heartBeatService.isShutdown()){
			if(heartBeatFuture != null){
				heartBeatFuture.cancel(true);
				heartBeatFuture = null;
			}
			heartBeatService.shutdown();
			heartBeatService = null;
		}
		if(service != null && !service.isShutdown()){
			if(future != null){
				future.cancel(true);
				future = null;
			}
			service.shutdown();
			service = null;
		}
		NotificationGenerator.shutdownNotificationWorkers();
	}

	public static void sendPacket(DatagramPacket packet){
		try {
			socket.send(packet);
		} catch (IOException e) {
			e.printStackTrace();
			// 发送失败，未作处理
		}
	}
}
